home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
User's Choice Windows CD
/
User's Choice Windows CD (CMS Software)(1993).iso
/
misc1
/
iv26_w30.zip
/
EXAMPLES
/
IDRAW
/
SLPICT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-17
|
25KB
|
750 lines
/*
* Copyright (c) 1987, 1988, 1989 Stanford University
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Stanford not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. Stanford makes no representations about
* the suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
* IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// $Header: slpict.c,v 1.19 89/10/09 14:49:34 linton Exp $
// implements class PictSelection.
#include "ipaint.h"
#include "istring.h"
#include "listifont.h"
#include "slellipses.h"
#include "sllines.h"
#include "slpict.h"
#include "slpolygons.h"
#include "slsplines.h"
#include "sltext.h"
#include <InterViews/transformer.h>
#include <iostream.h>
#include <fstream.h>
// PictSelection initializes its graphic state.
PictSelection::PictSelection (Graphic* gs) : (gs) {
valid = true;
}
// PictSelection knows it's the outermost PictSelection because it was
// called with a FILE* pointer, so it must read a version number, skip
// over its name, read its graphic state and children, and scale
// itself back to screen coordinates when it's finished.
PictSelection::PictSelection (FILE* stream, State* state) : (nil) {
int fd = fileno(stream);
istream from(fd);
ReadVersion(from);
ReadGridSpacing(from, state);
if (versionnumber < NONREDUNDANTVERSION) {
Skip(from);
}
ReadPictGS(from, state);
ReadChildren(from, state);
ScaleToScreenCoords();
Transformer* t = GetTransformer();
if (versionnumber < NONROTATEDVERSION && t != nil && t->Rotated90()) {
*t = identity;
Translate(0.0, -8.5*inches);
Rotate(90.0, 0.0, 0.0);
Picture::Propagate();
}
valid = from.good();
}
// Copy returns a copy of the PictSelection.
Graphic* PictSelection::Copy () {
Selection* copy = new PictSelection(this);
for (First(); !AtEnd(); Next()) {
copy->Append(GetCurrent()->Copy());
}
return copy;
}
// HasChildren returns true so Idraw can ungroup this Picture.
boolean PictSelection::HasChildren () {
return Picture::HasChildren();
}
// Propagate must preserve the PictSelection's transformation matrix
// if it has any.
void PictSelection::Propagate () {
Transformer* original = GetTransformer();
if (original != nil) {
original->Reference();
Picture::Propagate();
SetTransformer(original);
Unref(original);
} else {
Picture::Propagate();
}
}
// WritePicture writes the picture and returns true if the write
// succeeded or false if some IO error occurred. It omits the
// Postscript prologue and trailer if called with verbose false to
// speed up cutting and pasting pictures between drawings.
boolean PictSelection::WritePicture (
FILE* stream, State* state, boolean verbose
) {
#if !defined(__GNUG__)
// incompatible with g++, but works around a cfront bug
filebuf fb(stream->fd);
ostream to(&fb);
#else
int fd = fileno(stream);
ostream to(fd);
#endif
WritePicture(to, state, verbose);
return to.good();
}
// PictSelection knows it's not the outermost PictSelection so it only
// reads data to initialize its graphic state and create its children
// Selections.
PictSelection::PictSelection (istream& from, State* state) : (nil) {
ReadPictGS(from, state);
ReadChildren(from, state);
valid = from.good();
}
// ReadChildren loops determining which kind of Selection follows and
// creating it until it reads "end" which means all of the children
// have been created.
void PictSelection::ReadChildren (istream& from, State* state) {
while (from.good()) {
Skip(from);
Selection* child = nil;
from >> buf;
if (strcmp(buf, "BSpl") == 0) {
child = new BSplineSelection(from, state);
} else if (strcmp(buf, "Circ") == 0) {
child = new CircleSelection(from, state);
} else if (strcmp(buf, "CBSpl") == 0) {
child = new ClosedBSplineSelection(from, state);
} else if (strcmp(buf, "Elli") == 0) {
child = new EllipseSelection(from, state);
} else if (strcmp(buf, "Line") == 0) {
child = new LineSelection(from, state);
} else if (strcmp(buf, "MLine") == 0) {
child = new MultiLineSelection(from, state);
} else if (strcmp(buf, "Pict") == 0) {
child = new PictSelection(from, state);
} else if (strcmp(buf, "Poly") == 0) {
child = new PolygonSelection(from, state);
} else if (strcmp(buf, "Rect") == 0) {
child = new RectSelection(from, state);
} else if (strcmp(buf, "Text") == 0) {
child = new TextSelection(from, state);
} else if (strcmp(buf, "eop") == 0) {
break;
} else {
fprintf(stderr, "unknown Selection %s, skipping\n", buf);
continue;
}
if (from.good()) {
Append(child);
} else {
delete child;
}
}
}
// WritePicture writes the picture's data and Postscript code to print
// it wrapped in Postscript comments that minimally conform to version
// 1.0 of Adobe Systems's structuring conventions for Postscript. The
// picture must remove itself from its parent if it has a parent to
// prevent the parent's transformation from affecting the picture's
// calculation of its bounding box.
void PictSelection::WritePicture (ostream& to, State* state, boolean verbose) {
Picture* parent = (Picture*) Parent();
if (parent != nil) {
parent->SetCurrent(this);
parent->Remove(this);
}
ScaleToPostscriptCoords();
if (verbose) {
WriteComments(to);
WritePrologue(to);
WriteVersion(to);
WriteGridSpacing(to, state);
WriteDrawing(to);
WriteTrailer(to);
} else {
WriteVersion(to);
WriteDrawing(to);
}
ScaleToScreenCoords();
if (parent != nil) {
parent->InsertBeforeCur(this);
}
}
// WriteComments writes information about the picture such as the
// fonts used in it and the smallest bounding box enclosing it.
void PictSelection::WriteComments (ostream& to) {
to << "%!PS-Adobe-2.0 EPSF-1.2\n";
to << "%%DocumentFonts:";
int linelen = strlen("%%DocumentFonts:");
const int MAXLINELEN = 256;
IFontList* fontlist = new IFontList;
CollectFonts(fontlist);
for (fontlist->First(); !fontlist->AtEnd(); fontlist->Next()) {
IFont* font = fontlist->GetCur()->GetFont();
if (linelen + strlen(font->GetPrintFont()) + 2 <= MAXLINELEN) {
to << " ";
++linelen;
} else {
to << "\n%%+ ";
linelen = strlen("%%+ ");
}
to << font->GetPrintFont();
linelen += strlen(font->GetPrintFont());
}
to << "\n";
delete fontlist;
to << "%%Pages: 1\n";
Coord l, b, r, t;
GetBox(l, b, r, t);
to << "%%BoundingBox: " << l << " " << b << " " << r << " " << t << "\n";
to << "%%EndComments\n\n";
to << "50 dict begin\n\n";
}
// WritePrologue writes definitions of Postscript procedures to draw
// Selections. You should not rename or delete the "exported"
// capitalized procedures because old drawings rely on them, but you
// can rename or delete the "internal" uncapitalized procedures.
void PictSelection::WritePrologue (ostream& to) {
to << "/arrowHeight " << ARROWHEIGHT << " def\n";
to << "/arrowWidth " << ARROWWIDTH << " def\n";
to << "/none null def\n";
to << "/numGraphicParameters 17 def\n";
to << "/stringLimit 65535 def\n\n";
to << "/Begin {\n";
to << "save\n";
to << "numGraphicParameters dict begin\n";
to << "} def\n\n";
to << "/End {\n";
to << "end\n";
to << "restore\n";
to << "} def\n\n";
to << "/SetB {\n";
to << "dup type /nulltype eq {\n";
to << "pop\n";
to << "false /brushRightArrow idef\n";
to << "false /brushLeftArrow idef\n";
to << "true /brushNone idef\n";
to << "} {\n";
to << "/brushDashOffset idef\n";
to << "/brushDashArray idef\n";
to << "0 ne /brushRightArrow idef\n";
to << "0 ne /brushLeftArrow idef\n";
to << "/brushWidth idef\n";
to << "false /brushNone idef\n";
to << "} ifelse\n";
to << "} def\n\n";
to << "/SetCFg {\n";
to << "/fgblue idef\n";
to << "/fggreen idef\n";
to << "/fgred idef\n";
to << "} def\n\n";
to << "/SetCBg {\n";
to << "/bgblue idef\n";
to << "/bggreen idef\n";
to << "/bgred idef\n";
to << "} def\n\n";
to << "/SetF {\n";
to << "/printSize idef\n";
to << "/printFont idef\n";
to << "} def\n\n";
to << "/SetP {\n";
to << "dup type /nulltype eq {\n";
to << "pop true /patternNone idef\n";
to << "} {\n";
to << "/patternGrayLevel idef\n";
to << "patternGrayLevel -1 eq {\n";
to << "/patternString idef\n";
to << "} if\n";
to << "false /patternNone idef\n";
to << "} ifelse\n";
to << "} def\n\n";
to << "/BSpl {\n";
to << "0 begin\n";
to << "storexyn\n";
to << "newpath\n";
to << "n 1 gt {\n";
to << "0 0 0 0 0 0 1 1 true subspline\n";
to << "n 2 gt {\n";
to << "0 0 0 0 1 1 2 2 false subspline\n";
to << "1 1 n 3 sub {\n";
to << "/i exch def\n";
to << "i 1 sub dup i dup i 1 add dup i 2 add dup false subspline\n";
to << "} for\n";
to << "n 3 sub dup n 2 sub dup n 1 sub dup 2 copy false subspline\n";
to << "} if\n";
to << "n 2 sub dup n 1 sub dup 2 copy 2 copy false subspline\n";
to << "patternNone not brushLeftArrow not brushRightArrow not and and { ";
to << "ifill } if\n";
to << "brushNone not { istroke } if\n";
to << "0 0 1 1 leftarrow\n";
to << "n 2 sub dup n 1 sub dup rightarrow\n";
to << "} if\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/Circ {\n";
to << "newpath\n";
to << "0 360 arc\n";
to << "patternNone not { ifill } if\n";
to << "brushNone not { istroke } if\n";
to << "} def\n\n";
to << "/CBSpl {\n";
to << "0 begin\n";
to << "dup 2 gt {\n";
to << "storexyn\n";
to << "newpath\n";
to << "n 1 sub dup 0 0 1 1 2 2 true subspline\n";
to << "1 1 n 3 sub {\n";
to << "/i exch def\n";
to << "i 1 sub dup i dup i 1 add dup i 2 add dup false subspline\n";
to << "} for\n";
to << "n 3 sub dup n 2 sub dup n 1 sub dup 0 0 false subspline\n";
to << "n 2 sub dup n 1 sub dup 0 0 1 1 false subspline\n";
to << "patternNone not { ifill } if\n";
to << "brushNone not { istroke } if\n";
to << "} {\n";
to << "Poly\n";
to << "} ifelse\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/Elli {\n";
to << "0 begin\n";
to << "newpath\n";
to << "4 2 roll\n";
to << "translate\n";
to << "scale\n";
to << "0 0 1 0 360 arc\n";
to << "patternNone not { ifill } if\n";
to << "brushNone not { istroke } if\n";
to << "end\n";
to << "} dup 0 1 dict put def\n\n";
to << "/Line {\n";
to << "0 begin\n";
to << "2 storexyn\n";
to << "newpath\n";
to << "x 0 get y 0 get moveto\n";
to << "x 1 get y 1 get lineto\n";
to << "brushNone not { istroke } if\n";
to << "0 0 1 1 leftarrow\n";
to << "0 0 1 1 rightarrow\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/MLine {\n";
to << "0 begin\n";
to << "storexyn\n";
to << "newpath\n";
to << "n 1 gt {\n";
to << "x 0 get y 0 get moveto\n";
to << "1 1 n 1 sub {\n";
to << "/i exch def\n";
to << "x i get y i get lineto\n";
to << "} for\n";
to << "patternNone not brushLeftArrow not brushRightArrow not and and { ";
to << "ifill } if\n";
to << "brushNone not { istroke } if\n";
to << "0 0 1 1 leftarrow\n";
to << "n 2 sub dup n 1 sub dup rightarrow\n";
to << "} if\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/Poly {\n";
to << "3 1 roll\n";
to << "newpath\n";
to << "moveto\n";
to << "-1 add\n";
to << "{ lineto } repeat\n";
to << "closepath\n";
to << "patternNone not { ifill } if\n";
to << "brushNone not { istroke } if\n";
to << "} def\n\n";
to << "/Rect {\n";
to << "0 begin\n";
to << "/t exch def\n";
to << "/r exch def\n";
to << "/b exch def\n";
to << "/l exch def\n";
to << "newpath\n";
to << "l b moveto\n";
to << "l t lineto\n";
to << "r t lineto\n";
to << "r b lineto\n";
to << "closepath\n";
to << "patternNone not { ifill } if\n";
to << "brushNone not { istroke } if\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/Text {\n";
to << "ishow\n";
to << "} def\n\n";
to << "/idef {\n";
to << "dup where { pop pop pop } { exch def } ifelse\n";
to << "} def\n\n";
to << "/ifill {\n";
to << "0 begin\n";
to << "gsave\n";
to << "patternGrayLevel -1 ne {\n";
to << "fgred bgred fgred sub patternGrayLevel mul add\n";
to << "fggreen bggreen fggreen sub patternGrayLevel mul add\n";
to << "fgblue bgblue fgblue sub patternGrayLevel mul add setrgbcolor\n";
to << "eofill\n";
to << "} {\n";
to << "eoclip\n";
to << "originalCTM setmatrix\n";
to << "pathbbox /t exch def /r exch def /b exch def /l exch def\n";
to << "/w r l sub ceiling cvi def\n";
to << "/h t b sub ceiling cvi def\n";
to << "/imageByteWidth w 8 div ceiling cvi def\n";
to << "/imageHeight h def\n";
to << "bgred bggreen bgblue setrgbcolor\n";
to << "eofill\n";
to << "fgred fggreen fgblue setrgbcolor\n";
to << "w 0 gt h 0 gt and {\n";
to << "l b translate w h scale\n";
to << "w h true [w 0 0 h neg 0 h] { patternproc } imagemask\n";
to << "} if\n";
to << "} ifelse\n";
to << "grestore\n";
to << "end\n";
to << "} dup 0 8 dict put def\n\n";
to << "/istroke {\n";
to << "gsave\n";
to << "brushDashOffset -1 eq {\n";
to << "[] 0 setdash\n";
to << "1 setgray\n";
to << "} {\n";
to << "brushDashArray brushDashOffset setdash\n";
to << "fgred fggreen fgblue setrgbcolor\n";
to << "} ifelse\n";
to << "brushWidth setlinewidth\n";
to << "originalCTM setmatrix\n";
to << "stroke\n";
to << "grestore\n";
to << "} def\n\n";
to << "/ishow {\n";
to << "0 begin\n";
to << "gsave\n";
to << "fgred fggreen fgblue setrgbcolor\n";
to << "/fontDict printFont findfont printSize scalefont dup setfont def\n";
to << "/descender fontDict begin 0 [FontBBox] 1 get FontMatrix end\n";
to << "transform exch pop def\n";
to << "/vertoffset 0 descender sub printSize sub printFont /Courier ne\n";
to << "printFont /Courier-Bold ne and { 1 add } if def {\n";
to << "0 vertoffset moveto show\n";
to << "/vertoffset vertoffset printSize sub def\n";
to << "} forall\n";
to << "grestore\n";
to << "end\n";
to << "} dup 0 3 dict put def\n\n";
to << "/patternproc {\n";
to << "0 begin\n";
to << "/patternByteLength patternString length def\n";
to << "/patternHeight patternByteLength 8 mul sqrt cvi def\n";
to << "/patternWidth patternHeight def\n";
to << "/patternByteWidth patternWidth 8 idiv def\n";
to << "/imageByteMaxLength imageByteWidth imageHeight mul\n";
to << "stringLimit patternByteWidth sub min def\n";
to << "/imageMaxHeight imageByteMaxLength imageByteWidth idiv ";
to << "patternHeight idiv\n";
to << "patternHeight mul patternHeight max def\n";
to << "/imageHeight imageHeight imageMaxHeight sub store\n";
to << "/imageString imageByteWidth imageMaxHeight mul patternByteWidth ";
to << "add string def\n";
to << "0 1 imageMaxHeight 1 sub {\n";
to << "/y exch def\n";
to << "/patternRow y patternByteWidth mul patternByteLength mod def\n";
to << "/patternRowString patternString patternRow patternByteWidth ";
to << "getinterval def\n";
to << "/imageRow y imageByteWidth mul def\n";
to << "0 patternByteWidth imageByteWidth 1 sub {\n";
to << "/x exch def\n";
to << "imageString imageRow x add patternRowString putinterval\n";
to << "} for\n";
to << "} for\n";
to << "imageString\n";
to << "end\n";
to << "} dup 0 12 dict put def\n\n";
to << "/min {\n";
to << "dup 3 2 roll dup 4 3 roll lt { exch } if pop\n";
to << "} def\n\n";
to << "/max {\n";
to << "dup 3 2 roll dup 4 3 roll gt { exch } if pop\n";
to << "} def\n\n";
to << "/arrowhead {\n";
to << "0 begin\n";
to << "transform originalCTM itransform\n";
to << "/taily exch def\n";
to << "/tailx exch def\n";
to << "transform originalCTM itransform\n";
to << "/tipy exch def\n";
to << "/tipx exch def\n";
to << "/dy tipy taily sub def\n";
to << "/dx tipx tailx sub def\n";
to << "/angle dx 0 ne dy 0 ne or { dy dx atan } { 90 } ifelse def\n";
to << "gsave\n";
to << "originalCTM setmatrix\n";
to << "tipx tipy translate\n";
to << "angle rotate\n";
to << "newpath\n";
to << "0 0 moveto\n";
to << "arrowHeight neg arrowWidth 2 div lineto\n";
to << "arrowHeight neg arrowWidth 2 div neg lineto\n";
to << "closepath\n";
to << "patternNone not {\n";
to << "originalCTM setmatrix\n";
to << "/padtip arrowHeight 2 exp 0.25 arrowWidth 2 exp mul add sqrt ";
to << "brushWidth mul\n";
to << "arrowWidth div def\n";
to << "/padtail brushWidth 2 div def\n";
to << "tipx tipy translate\n";
to << "angle rotate\n";
to << "padtip 0 translate\n";
to << "arrowHeight padtip add padtail add arrowHeight div dup scale\n";
to << "arrowheadpath\n";
to << "ifill\n";
to << "} if\n";
to << "brushNone not {\n";
to << "originalCTM setmatrix\n";
to << "tipx tipy translate\n";
to << "angle rotate\n";
to << "arrowheadpath\n";
to << "istroke\n";
to << "} if\n";
to << "grestore\n";
to << "end\n";
to << "} dup 0 9 dict put def\n\n";
to << "/arrowheadpath {\n";
to << "newpath\n";
to << "0 0 moveto\n";
to << "arrowHeight neg arrowWidth 2 div lineto\n";
to << "arrowHeight neg arrowWidth 2 div neg lineto\n";
to << "closepath\n";
to << "} def\n\n";
to << "/leftarrow {\n";
to << "0 begin\n";
to << "y exch get /taily exch def\n";
to << "x exch get /tailx exch def\n";
to << "y exch get /tipy exch def\n";
to << "x exch get /tipx exch def\n";
to << "brushLeftArrow { tipx tipy tailx taily arrowhead } if\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/rightarrow {\n";
to << "0 begin\n";
to << "y exch get /tipy exch def\n";
to << "x exch get /tipx exch def\n";
to << "y exch get /taily exch def\n";
to << "x exch get /tailx exch def\n";
to << "brushRightArrow { tipx tipy tailx taily arrowhead } if\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/midpoint {\n";
to << "0 begin\n";
to << "/y1 exch def\n";
to << "/x1 exch def\n";
to << "/y0 exch def\n";
to << "/x0 exch def\n";
to << "x0 x1 add 2 div\n";
to << "y0 y1 add 2 div\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/thirdpoint {\n";
to << "0 begin\n";
to << "/y1 exch def\n";
to << "/x1 exch def\n";
to << "/y0 exch def\n";
to << "/x0 exch def\n";
to << "x0 2 mul x1 add 3 div\n";
to << "y0 2 mul y1 add 3 div\n";
to << "end\n";
to << "} dup 0 4 dict put def\n\n";
to << "/subspline {\n";
to << "0 begin\n";
to << "/movetoNeeded exch def\n";
to << "y exch get /y3 exch def\n";
to << "x exch get /x3 exch def\n";
to << "y exch get /y2 exch def\n";
to << "x exch get /x2 exch def\n";
to << "y exch get /y1 exch def\n";
to << "x exch get /x1 exch def\n";
to << "y exch get /y0 exch def\n";
to << "x exch get /x0 exch def\n";
to << "x1 y1 x2 y2 thirdpoint\n";
to << "/p1y exch def\n";
to << "/p1x exch def\n";
to << "x2 y2 x1 y1 thirdpoint\n";
to << "/p2y exch def\n";
to << "/p2x exch def\n";
to << "x1 y1 x0 y0 thirdpoint\n";
to << "p1x p1y midpoint\n";
to << "/p0y exch def\n";
to << "/p0x exch def\n";
to << "x2 y2 x3 y3 thirdpoint\n";
to << "p2x p2y midpoint\n";
to << "/p3y exch def\n";
to << "/p3x exch def\n";
to << "movetoNeeded { p0x p0y moveto } if\n";
to << "p1x p1y p2x p2y p3x p3y curveto\n";
to << "end\n";
to << "} dup 0 17 dict put def\n\n";
to << "/storexyn {\n";
to << "/n exch def\n";
to << "/y n array def\n";
to << "/x n array def\n";
to << "n 1 sub -1 0 {\n";
to << "/i exch def\n";
to << "y i 3 2 roll put\n";
to << "x i 3 2 roll put\n";
to << "} for\n";
to << "} def\n\n";
to << "%%EndProlog\n\n";
}
// WriteDrawing writes code to store the picture's transformation
// matrix in a Postscript variable and code to draw the picture.
void PictSelection::WriteDrawing (ostream& to) {
to << "\n\n%%Page: 1 1\n\n";
to << "Begin\n";
WritePictGS(to);
to << "/originalCTM matrix currentmatrix def\n\n";
for (First(); !AtEnd(); Next()) {
Selection* s = GetCurrent();
s->WriteData(to);
}
to << "End " << startdata << " eop\n\n";
to << "showpage\n\n";
}
// WriteData writes the PictSelection's data and its children
// Selections' data with Postscript code to draw them.
void PictSelection::WriteData (ostream& to) {
to << "Begin " << startdata << " Pict\n";
WritePictGS(to);
to << "\n";
for (First(); !AtEnd(); Next()) {
Selection* s = GetCurrent();
s->WriteData(to);
}
to << "End " << startdata << " eop\n\n";
}
// WriteTrailer writes clean up code.
void PictSelection::WriteTrailer (ostream& to) {
to << "%%Trailer\n\n";
to << "end\n";
}
// ScaleToPostscriptCoords scales the picture to Postscript
// coordinates if screen and Postscript inches are different.
void PictSelection::ScaleToPostscriptCoords () {
const double postscriptinch = 72.;
if (inch != postscriptinch) {
double topostscript = postscriptinch / inch;
Scale(topostscript, topostscript);
}
}
// ScaleToScreenCoords scales the picture back to screen coordinates
// if screen and Postscript inches are different.
void PictSelection::ScaleToScreenCoords () {
const double postscriptinch = 72.;
if (inch != postscriptinch) {
double toscreen = inch / postscriptinch;
Scale(toscreen, toscreen);
}
}
// CollectFonts adds its font, if it has one, to the list without
// checking if the PictSelection contains any TextSelections. If it
// doesn't have a font, it collects its children TextSelection's
// fonts.
void PictSelection::CollectFonts (IFontList* fontlist) {
if (GetFont() != nil) {
Merge((IFont*) GetFont(), fontlist);
} else {
for (First(); !AtEnd(); Next()) {
Selection* s = GetCurrent();
if (s->HasChildren()) {
((PictSelection*) s)->CollectFonts(fontlist);
} else if (s->IsA(TEXTSELECTION)) {
Merge((IFont*) s->GetFont(), fontlist);
}
}
}
}
// Merge merges the print font with the list of all print fonts unless
// the list already has it.
void PictSelection::Merge (IFont* font, IFontList* fontlist) {
boolean found = false;
if (font == nil) {
found = true;
} else if (fontlist->Find(font)) {
found = true;
} else {
for (fontlist->First(); !fontlist->AtEnd(); fontlist->Next()) {
IFont* cmp = fontlist->GetCur()->GetFont();
if (strcmp(font->GetPrintFont(), cmp->GetPrintFont()) == 0) {
found = true;
break;
}
}
}
if (!found) {
fontlist->Append(new IFontNode(font));
}
}